﻿namespace MDXStudio.QueryEditor
{
    using System;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;

    internal class ParserUtil
    {
        private static readonly Regex sRegExBlockComments = new Regex(@"(?<blockcomment>(?sx:(?:((?<left>(/\*))|(?<right-left>(\*/)))|(?(left)((?!\*/).)*|[$]))+)+)", RegexOptions.CultureInvariant | RegexOptions.Compiled);
        private static readonly Regex sRegExBrackets;
        private static readonly Regex sRegExCombination;
        private static readonly Regex sRegExKeyWords;
        private static readonly Regex sRegExLineComments = new Regex("(?<linecomment>(?m:(//.*|--.*)))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
        private static readonly Regex sRegExNumber = new Regex(@"(?<number>(?-sx:((^|\s+|\()\d+)|(\s*\.\d+\)?)|((^|\s+)\d+\.)|((^|\s)+\d+\.)))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
        private static readonly Regex sRegExOperators;
        private static readonly Regex sRegExString = new Regex("(?<string>(?s:((\"[^\"]*)(\"|$))))", RegexOptions.Compiled);
        private static readonly Regex sRegExSysFunc;

        static ParserUtil()
        {
            sRegExNumber = new Regex(@"(?x:(?<number>((\d+)|((\s|\d*)\.\d+)|(\d+\.))))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            sRegExOperators = new Regex(@"(?<operators1>(?x:(\*)|(/)|(\.|,|\(|\)|\+|-|<|<=|=|>=|<>|>|\^|%|!=|!<|!>|\|~)+))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            sRegExBrackets = new Regex(@"(?<brackets>(?xm:(?:((?<left>(\[))|(?<right-left>(\])))|(?(left)((?!\]).)*|[$]))+)+)", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            sRegExKeyWords = new Regex(@"(?<keyword>(?x:(\b((after|all|and|as|asc|axis|basc|bdesc|before|before_and_after|by|cell|columns|count|create|default_member|desc|description|dimensions|empty|end|excludeempty|false|for|freeze|from|includeempty|is|item|lag|measure|member|members|name|non|null|on|or|post|properties|property|recursive|rows|scope|select|self|self_and_after|self_and_before|self_before_after|session|set|this|true|type|uniquename|update|use|username|value|variance|where|with|xor|member_key|parent_unique_name|parent_level|dimension_unique_name|hierarchy_unique_name|cube_name)\b))))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            sRegExSysFunc = new Regex(@"(?<sysfunc>(?x:(\b((ascendants|currentordinal|exists|order|ordinal|unknownmember|unorder|addcalculatedmembers|aggregate|allmembers|ancestor|ancestors|ascendants|avg|bottomcount|bottompercent|bottomsum|children|closingperiod|cousin|crossjoin|current|currentmember|defaultmember|descendants|dimension|distinct|distinctcount|drilldownlevel|except|extract|filter|firstchild|firstsibling|generate|head|hierarchy|iif|intersect|isancestor|isempty|isgeneration|isleaf|issibling|lastchild|lastperiods|lastsibling|lead|leaves|level|levels|linkmember|max|membertostr|min|mtd|nametoset|nextmember|nonemptycrossjoin|openingperiod|parallelperiod|parent|periodstodate|predict|prevmember|qtd|rank|rollupchildren|root|settoarray|settostr|sort|stripcalculatedmembers|strtomember|strtoset|strtotuple|strtoval|strtovalue|subset|sum|tail|topcount|toppercent|topsum|tupletostr|union|unique|validmeasure|visualtotals|wtd|ytd)\b))))", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            sRegExCombination = new Regex(@"([A-Za-z]\d+)", RegexOptions.CultureInvariant | RegexOptions.Compiled);
        }

        public static void CheckRegExsLoadList(string pText, List<TextSegment> pList)
        {
            pText = pText.ToLowerInvariant();
            MatchCollection pMatches = sRegExKeyWords.Matches(pText);
            MatchCollection matchs5 = sRegExLineComments.Matches(pText);
            MatchCollection matchs = sRegExBlockComments.Matches(pText);
            MatchCollection matchs2 = sRegExBrackets.Matches(pText);
            MatchCollection matchs6 = sRegExOperators.Matches(pText);
            MatchCollection matchs7 = sRegExNumber.Matches(pText);
            MatchCollection matchs8 = sRegExString.Matches(pText);
            MatchCollection matchs9 = sRegExSysFunc.Matches(pText);
            MatchCollection matchs3 = sRegExCombination.Matches(pText);
            LoadListOfMatches(pList, pMatches, eHighlightType.KeyWord);
            LoadListOfMatches(pList, matchs9, eHighlightType.SystemFunction);
            LoadListOfMatches(pList, matchs5, eHighlightType.LineComment);
            LoadListOfMatches(pList, matchs, eHighlightType.BlockComment);
            LoadListOfMatches(pList, matchs2, eHighlightType.PlainText);
            LoadListOfMatches(pList, matchs6, eHighlightType.Operator);
            LoadListOfMatches(pList, matchs7, eHighlightType.Number);
            LoadListOfMatches(pList, matchs8, eHighlightType.String);
            LoadListOfMatches(pList, matchs3, eHighlightType.PlainText);
        }

        private static void LoadListOfMatches(IList<TextSegment> pTextSegmentList, MatchCollection pMatches, eHighlightType pHighlightType)
        {
            foreach (Match match in pMatches)
            {
                if (match.Success && (match.Length > 0))
                {
                    TextSegment item = new TextSegment(pHighlightType, match.Index, match.Length);
                    pTextSegmentList.Add(item);
                }
            }
        }
    }
}

